package com.zyplayer.doc.git.service;

import cn.hutool.json.JSONUtil;
import com.zyplayer.doc.git.utils.FilesUtils;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PullResult;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import javax.annotation.PostConstruct;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

@RequiredArgsConstructor
public class GitService {

    private static final Logger logger = LoggerFactory.getLogger(GitService.class);
    @Value("${zyplayer.doc.wiki.git-local-path:}")
    private String gitLocalPath;
    @Value("${zyplayer.doc.wiki.git-remote-url:}")
    private String gitRemoteUrl;
    @Value("${zyplayer.doc.wiki.git-remote-username:}")
    private String gitRemoteUsername;
    @Value("${zyplayer.doc.wiki.git-remote-password:}")
    private String gitRemotePassword;
    @Value("${zyplayer.doc.wiki.git-remote-branch:}")
    private String gitRemoteBranch;


    @Getter
    private Git git;

    private UsernamePasswordCredentialsProvider credentialsProvider;

    /**
     * 1.判断本地仓库目录是否存在（因3 而忽略）
     * 2.判断.git目录是否存在（因3 而忽略）
     * 3.尝试拉取远程仓库到本地
     * <p>
     * https://zhuanlan.zhihu.com/p/96772615
     */
    @PostConstruct
    void connectGitRepository() {
        if (StringUtils.isBlank(gitRemoteUrl)) {
            logger.warn("没有开启远程仓库。如果需要，请配置远程仓库信息");
            return;
        }
        if (StringUtils.isNotBlank(gitRemoteUrl)
                && (StringUtils.isBlank(gitRemoteUsername) || StringUtils.isBlank(gitRemotePassword))) {
            //如果不需要远程仓库，需要把 远程仓库地址移除
            logger.error("Git登录失败，账号或密码不正确. 如果不需要远程仓库，请移除gitRemoteUrl配置");
            return;
        }
        credentialsProvider =
                new UsernamePasswordCredentialsProvider(gitRemoteUsername, gitRemotePassword);

        try {
            File gitLocalDir = new File(gitLocalPath);
            logger.info("父级{}目录是否存在：{}", gitLocalDir, gitLocalDir.exists());
            // 如果gitLocalPath目录存在 则清空目录
            if (gitLocalDir.exists()) {
                FilesUtils.delAllFile(gitLocalPath, new ArrayList<>());
            }
            //创建目录
            gitLocalDir.mkdirs();
            //程序每次启动 都尝试拉取最新的远程仓库
            git = Git.cloneRepository()
                    .setDirectory(gitLocalDir)
                    .setURI(gitRemoteUrl)
                    .setBranch(gitRemoteBranch)
                    .setCredentialsProvider(credentialsProvider)
                    .call();
            logger.info("克隆远程仓库成功：{} {} ", gitRemoteBranch, gitRemoteUrl);

            //确保本地仓库和远程仓库一致
            Calendar instance = Calendar.getInstance();
            Date time = instance.getTime();

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String formattedDate = sdf.format(time);

            this.oneClickPush("项目启动-备份执行时间: " + formattedDate);

            logger.info("克隆远程仓库到本地仓库成功,本地仓库目录为: {}", gitLocalDir.getAbsolutePath());
        } catch (GitAPIException e) {
            throw new RuntimeException(".git文件初始化失败: " + e.getMessage());
        } catch (Exception e) {
//            throw new RuntimeException("Git仓库初始化失败：" + e.getMessage());
            e.printStackTrace();
        }
    }


    /**
     * clone 远程仓库
     *
     * @return
     * @throws GitAPIException
     */
    public Git gitClone() throws GitAPIException {
        return Git.cloneRepository()
                .setDirectory(new File(gitLocalPath))
                .setURI(gitRemoteUrl)
                .setBranch(gitRemoteBranch)
                .setCredentialsProvider(credentialsProvider)
                .call();
    }

    /**
     * pull 最新内容
     *
     * @return
     * @throws GitAPIException
     */
    public PullResult gitPull() throws GitAPIException {
        return git.pull()
                .setRemoteBranchName(gitRemoteBranch)
                .setCredentialsProvider(credentialsProvider)
                .call();
    }

    /**
     * add 命令
     *
     * @return
     * @throws GitAPIException
     */
    public DirCache gitAdd() throws GitAPIException {
        return git.add()
                .addFilepattern(".")
                .call();
    }

    /**
     * commit 提交文件到本地
     *
     * @param msg
     * @return
     * @throws GitAPIException
     */
    public RevCommit gitCommit(String msg) throws GitAPIException {
        return git.commit()
                .setAll(true)
                .setMessage(StringUtils.defaultString(msg, ""))
                .call();
    }

    /**
     * push 提交本地仓库带远程仓库
     *
     * @return
     * @throws GitAPIException
     */
    public Iterable<PushResult> gitPush() throws GitAPIException {
        return git.push()
                .setCredentialsProvider(credentialsProvider).call();
    }


    /**
     * 一键提交文件到远程仓库
     *
     * @param commitMsg
     * @throws GitAPIException
     */
    public void oneClickPush(String commitMsg) throws GitAPIException {
        PullResult pullResult = this.gitPull();
        logger.info("git pull result: {}", JSONUtil.toJsonStr(pullResult));
        DirCache dirCache = this.gitAdd();
        logger.info("git add result: {}", JSONUtil.toJsonStr(dirCache));
        RevCommit revCommit = this.gitCommit(commitMsg);
        logger.info("git commit result: {}", JSONUtil.toJsonStr(revCommit));
        Iterable<PushResult> pushResults = this.gitPush();
        logger.info("git push result: {}", JSONUtil.toJsonStr(pushResults));
    }

}
